import os
import csv
import re


"""

该脚本的执行时机：
再运行 c-lop_analyze.py 之后，想要统计每一个文件的误差


该文件的作用:
会遍历所有的文件，提取最后一行的 comm_type、total_real_comm_time、c_lop_prediction_for_total_time 这三列
并计算 |total_real_comm_time - predict_total_comm_time| / total_real_comm_time 这一列，并保存到 summary.csv 中

"""


def extract_config_row(csv_path, target_comm_type):
    """根据指定的comm_type提取对应行的数据"""
    try:
        with open(csv_path, 'r', newline='') as f:
            reader = csv.reader(f)
            header = next(reader)  # 读取标题行
            
            # 获取所需列的索引
            try:
                comm_type_idx = header.index('comm_type')
                real_time_idx = header.index('total_real_comm_time')
                predict_idx = header.index('c_lop_prediction_for_total_time')
            except ValueError as e:
                print(f"列名缺失: {e} in {csv_path}")
                return None
            
            # 查找匹配的行
            for row in reader:
                if row[comm_type_idx] == target_comm_type:
                    return {
                        'comm_type': row[comm_type_idx],
                        'total_real_comm_time': row[real_time_idx],
                        'predict_total_comm_time': row[predict_idx]
                    }
            
            # 如果没有找到匹配的行
            print(f"未找到comm_type为'{target_comm_type}'的行 in {csv_path}")
            return None
            
    except Exception as e:
        print(f"处理文件出错 {csv_path}: {e}")
        return None

def process_csv_files(base_dir, target_dir, extract_config):
    """主处理函数：遍历目录并生成汇总CSV"""
    output_path = os.path.join(target_dir, 'summary.csv')
    processed_count = 0
    skipped_count = 0

    with open(output_path, 'w', newline='') as outfile:
        writer = csv.DictWriter(outfile, fieldnames=[
            'base_dir', 'node_dir', 'proc_dir','comm_type',
            'total_real_comm_time', 'predict_total_comm_time','|total_real_comm_time - predict_total_comm_time| / total_real_comm_time'
        ])
        writer.writeheader()

        # 直接处理base_dir中的CSV文件
        # 遍历base_dir的直接子文件夹
        for subdir in os.listdir(base_dir):
            subdir_path = os.path.join(base_dir, subdir)
            if not os.path.isdir(subdir_path):
                continue

            # 处理子文件夹中的CSV文件
            for filename in os.listdir(subdir_path):
                if not filename.lower().endswith('.csv'):
                    continue
                
                csv_path = os.path.join(subdir_path, filename)
                row_data = extract_config_row(csv_path, extract_config)
                
                if not row_data:
                    skipped_count += 1
                    continue

                writer.writerow({
                    'base_dir': filename,
                    'node_dir': extract_node_info(filename),
                    'proc_dir': extract_proc_info(filename),
                    'comm_type': row_data['comm_type'],
                    'total_real_comm_time': row_data['total_real_comm_time'],
                    'predict_total_comm_time': row_data['predict_total_comm_time'],
                    '|total_real_comm_time - predict_total_comm_time| / total_real_comm_time': (abs(float(row_data['total_real_comm_time']) - float(row_data['predict_total_comm_time'])) / float(row_data['total_real_comm_time']) )* 100
                })
                processed_count += 1
    
    print(f"处理完成: 成功处理 {processed_count} 个文件, 跳过 {skipped_count} 个文件")
    print(f"结果已保存至: {output_path}")
    print(f"使用的提取配置: {extract_config}")


# 从文件名中提取 cn信息
def extract_cn_info(node_dir):
    """
    从node_dir字符串中提取cn[]或cnxx格式的节点信息
    1. 优先匹配cn[...]格式（如cn[8473-8474]）
    2. 其次匹配cnxx格式（如cn8473）
    3. 都未匹配到时返回空字符串
    """
    # 匹配cn[...]格式（如cn[8473-8474,9544-9545]）
    cn_bracket_match = re.search(r'cn\[([^\]]+)\]', node_dir)
    if cn_bracket_match:
        return f"cn[{cn_bracket_match.group(1)}]"
    
    # 匹配cnxx格式（如cn8473）
    cn_digit_match = re.search(r'cn\d+', node_dir)
    if cn_digit_match:
        return cn_digit_match.group(0)
    
    return ""  # 未匹配到任何格式

# 提取节点信息
def extract_node_info(node_dir):
    # 匹配 xxnode格式（如4node）
    node_match = re.search(r'\d+node', node_dir)
    if node_match:
        return node_match.group(0)
    return "" # 未匹配到任何格式

# 提取进行信息
def extract_proc_info(proc_dir):
    # 匹配 xxproc格式（如4proc）
    proc_match = re.search(r'\d+proc', proc_dir)
    if proc_match:
        return proc_match.group(0)
    return "" # 未匹配到任何格式
    
if __name__ == '__main__':


    # 配置路径 (根据实际需求修改)
    # base_dir = r'F:\PostGraduate\Point-to-Point-DATA\deal-data-code\C-lop-Prediction\analysis_for_all_comm_size\new1-16nodes-data'  # 替换为实际基础目录
    base_dir = r'F:\PostGraduate\Point-to-Point-Code\App_Prediction\analysis_weak_scaling\analysis_for_100atom_per_proc'  # 替换为实际基础目录
    target_dir =  os.path.join(base_dir,'all_predict_precision')

    #配置一般有这几种
    # Total_C-lop_prediction_comm_type_50
    # Total_C-lop_prediction_comm_type_51
    # Total_C-lop_prediction_comm_type_55
    # Total_C-lop_prediction
    extract_config = "Total_C-lop_prediction_comm_type_51"

    
    # 确保目标目录存在
    os.makedirs(target_dir, exist_ok=True)
    
    # 执行处理
    # 执行处理
    process_csv_files(base_dir, target_dir, extract_config)
